(defun bsearch(l n &optional (start 0) (offset (length l)))
;  (format t "~d -> ~d middle ~d = ~d~%" start offset (floor (/ offset 2)) (elt l (+ start (floor (/ offset 2)))) )
  (cond ((> 1 offset) nil)
	((= 1 offset) (= n (elt l (1+ start))))
	((= n (elt l (+ start (floor (/ offset 2))))) t)
	(t (bsearch l n (if (< n (elt l (+ start (floor (/ offset 2))))) start (+ start (floor (/ offset 2)))) (floor (/ offset 2))))))

(defun primep(n)
  (cond 
    ((< n 0) (primep (- n)))
    ((<= n 3) t)
    ((zerop (mod n 2)) nil)
    (t (loop 
	  for i = 3 then (+ 2 i) 
	  with lim = (sqrt n) 
	  while (<= i lim) 
	  when (zerop (mod n i)) do (return nil) 
	  finally (return t)))))

(defparameter *primes* (make-array 665025 :initial-element 0 :fill-pointer 0 :adjustable nil :element-type 'fixnum ))

(defun init-primes(primes)
  (loop for i from 1 to 10000000 when (primep i) do (vector-push i primes)))

(init-primes *primes*)

(defun fast-prime (n)
  (if (> 9999992 n) (bsearch *primes* n) (primep n)))

(defun digits(n)
  (loop for i = n then (floor (/ i 10))
       while (> i 0)
       collect (mod i 10)))

(defun make-no(l)
  (if (null l) 0 (+ (car l) (* 10 (make-no (cdr l))))))

(defun smart-pattern(a b)
  (loop for i in a 
     for j in b 
     with res = nil 
;     with carry = -1
     do (if (= i j) (setf res (cons i res)) (setf res (cons nil res)))
     finally (return (nreverse res))))

(defun smart-make-no(l dig)
  (if (null l) 0 (+ 
		  (if (null (car l)) dig (car l))
		  (* 10 (smart-make-no (cdr l) dig)))))

(defun test-has-primes(pattern primes)
  (loop for i from 0 to 9 
     for no = (smart-make-no pattern i) 
     with p = 0 with np = 0
     when (> np (- 10 primes)) do (return nil)
     when (= p primes) do (return t)
     do (if (fast-prime no) (incf p) (incf np))))  

(defun print-pattern(pattern)
  (loop for i from 0 to 9
     for no = (smart-make-no pattern i)
     when (fast-prime no)
     collect no))
	 
(defun find-primes-group(target l1 &optional (l2 (cdr l1)))
  (cond ((null l1) nil)
	((null l2) (find-primes-group target (cdr l1) (cddr l1)))
	((test-has-primes (smart-pattern (car l1) (car l2)) target) (smart-pattern (car l1) (car l2)))
	(t (find-primes-group target l1 (cdr l2) ))))

(defun find-primes(target start end)
  (loop for i from start to (1- end)
     when (fast-prime i) 
     do (loop for j from (1+ i) to end 
	   when (fast-prime j)
	   do (if (test-has-primes (smart-pattern (digits i) (digits j)) target) (print (print-pattern (smart-pattern (digits i) (digits j))))))))